const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class LxPromise {
  value = undefined;
  reason = undefined;
  status = PENDING;
  successCallback = [];
  failCallback = [];

  constructor(executor) {
    executor(this.resolve, this.reject);
  }

  static resolve(value) {
    if (value instanceof LxPromise) return value;
    return new LxPromise((resolve) => resolve(value));
  }

  static reject(reason) {
    if (reason instanceof LxPromise) return reason;
    return new LxPromise((resolve, reject) => reject(reason));
  }

  static all(array) {
    return new LxPromise((resolve) => {
      let arr = [];
      let index = 0;

      function setArr(key, value) {
        arr[key] = value;
        index++;
        if (index === array.length) {
          resolve(arr);
        }
      }

      for (let i = 0; i < array.length; i++) {
        const current = array[i];
        if (current instanceof LxPromise) {
          current.then((res) => {
            setArr(i, res);
          });
        } else {
          setArr(i, current);
        }
      }
    });
  }

  resolve = (value) => {
    if (this.status !== PENDING) return false;
    this.value = value;
    this.status = FULFILLED;
    while (this.successCallback.length) this.successCallback.shift()(value);
  };

  reject = (reason) => {
    if (this.status !== REJECTED) return false;
    this.reason = reason;
    this.status = REJECTED;
    while (this.failCallback.length) this.failCallback.shift()(reason);
  };

  then = (successCallback, failCallback) => {
    successCallback = successCallback ? successCallback : (value) => value;
    failCallback = failCallback
      ? failCallback
      : (reason) => {
        throw reason;
      };
    let promise2 = new LxPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        let x = successCallback(this.value);
        disposePromiseThen(x, resolve, reject);
        // resolve(successCallback(this.value));
      } else if (this.status === REJECTED) {
        let x = failCallback(this.reason);
        disposePromiseThen(x, resolve, reject);
        reject(failCallback(this.reason));
      } else {
        this.successCallback.push(() => {
          let x = successCallback(this.value);
          disposePromiseThen(x, resolve, reject);
        });

        this.failCallback.push(() => {
          let x = failCallback(this.reason);
          disposePromiseThen(x, resolve, reject);
        });
      }
    });
    return promise2;
  };

  catch(failCallback) {
    return this.then(undefined, failCallback);
  }
}

/**
 * 判断上一个promise返回的是 promise对象 还是 变量值
 * */
function disposePromiseThen(x, resolve, reject) {
  if (x instanceof LxPromise) {
    x.then(resolve, reject);
  } else {
    resolve(x);
  }
}

let lx_promise = new LxPromise((resolve, reject) => {
  console.log("开始");
  setTimeout(() => {
    resolve(1);
  }, 2000);
});

lx_promise
  .then((res) => {
    console.log(res);
    let p1 = new LxPromise((resolve) => {
      resolve("测试p1");
    });
    return p1;
  })
  .then((res) => {
    console.log(res);
  });
